using AutoMapper;
using B.S.NewMedical.Api.Read.Application.Command.Doctor;
using B.S.NewMedical.Api.Read.DTOS.Doctor;
using B.S.NewMedical.Domain.Doctor;
using B.S.NewMedical.Domain.Hospital;
using B.S.NewMedical.ErrorCode;
using B.S.NewMedical.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.NewMedical.Api.Read.Application.Handler.Doctor
{
    /// <summary>
    /// 获取开单申请表列表处理器
    /// </summary>
    public class GetPrescriptionApplicationsHandler : IRequestHandler<GetPrescriptionApplicationsCommand, ApiResult<List<PrescriptionApplicationDto>>>
    {
        private readonly IBaseRepository<PrescriptionApplicationModel> _prescriptionApplicationRepository;
        private readonly IBaseRepository<PrescriptionDetailModel> _prescriptionDetailRepository;
        private readonly IBaseRepository<HospitalModel> _hospitalRepository;
        private readonly IBaseRepository<DrugInfoModel> _drugRepository;
        private readonly IBaseRepository<CheckupItemModel> _checkupItemRepository;
        private readonly IBaseRepository<TestItemModel> _testItemRepository;
        private readonly ILogger<GetPrescriptionApplicationsHandler> _logger;
        private readonly IMapper _mapper;

        public GetPrescriptionApplicationsHandler(
            IBaseRepository<PrescriptionApplicationModel> prescriptionApplicationRepository,
            IBaseRepository<PrescriptionDetailModel> prescriptionDetailRepository,
            IBaseRepository<HospitalModel> hospitalRepository,
            IBaseRepository<DrugInfoModel> drugRepository,
            IBaseRepository<CheckupItemModel> checkupItemRepository,
            IBaseRepository<TestItemModel> testItemRepository,
            ILogger<GetPrescriptionApplicationsHandler> logger,
            IMapper mapper)
        {
            _prescriptionApplicationRepository = prescriptionApplicationRepository;
            _prescriptionDetailRepository = prescriptionDetailRepository;
            _hospitalRepository = hospitalRepository;
            _drugRepository = drugRepository;
            _checkupItemRepository = checkupItemRepository;
            _testItemRepository = testItemRepository;
            _logger = logger;
            _mapper = mapper;
        }

        public async Task<ApiResult<List<PrescriptionApplicationDto>>> Handle(GetPrescriptionApplicationsCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始获取开单申请列表，用户ID：{UserId}，状态：{Status}，页码：{PageIndex}，页大小：{PageSize}",
                    request.UserId, request.Status, request.PageIndex, request.PageSize);

                // 查询开单申请表
                var query = _prescriptionApplicationRepository.GetAll().Where(p => !p.IsDeleted);

                // 按用户ID筛选
                if (request.UserId.HasValue)
                {
                    query = query.Where(p => p.UserId == request.UserId.Value);
                }

                // 按状态筛选
                if (request.Status.HasValue)
                {
                    query = query.Where(p => p.Status == request.Status.Value);
                }

                // 分页
                var applications = await query
                    .OrderByDescending(p => p.ApplicationTime)
                    .Skip((request.PageIndex - 1) * request.PageSize)
                    .Take(request.PageSize)
                    .ToListAsync(cancellationToken);

                // 获取医院信息
                var hospitalIds = applications.Select(a => a.HospitalId).Distinct().ToList();
                var hospitals = await _hospitalRepository.GetAll()
                    .Where(h => hospitalIds.Contains(h.Id) && !h.IsDeleted)
                    .ToDictionaryAsync(h => h.Id, h => h, cancellationToken);

                // 转换为DTO
                var applicationDtos = new List<PrescriptionApplicationDto>();
                foreach (var application in applications)
                {
                    var dto = _mapper.Map<PrescriptionApplicationDto>(application);
                    
                    // 设置医院名称
                    if (hospitals.TryGetValue(application.HospitalId, out var hospital))
                    {
                        dto.HospitalName = hospital.HospitalName;
                    }

                    // 设置状态名称
                    dto.StatusName = GetStatusName(application.Status);

                    // 添加到结果集
                    applicationDtos.Add(dto);
                }

                // 如果需要加载明细
                if (request.IncludeDetails)
                {
                    var applicationIds = applications.Select(a => a.Id).ToList();
                    var details = await _prescriptionDetailRepository.GetAll()
                        .Where(d => applicationIds.Contains(d.ApplicationId) && !d.IsDeleted)
                        .ToListAsync(cancellationToken);

                    // 获取药品、检查项目、检验项目的ID集合
                    var drugIds = details.Where(d => d.ItemType == 1).Select(d => d.ItemId).Distinct().ToList();
                    var checkupIds = details.Where(d => d.ItemType == 2).Select(d => d.ItemId).Distinct().ToList();
                    var testIds = details.Where(d => d.ItemType == 3).Select(d => d.ItemId).Distinct().ToList();

                    // 查询药品信息
                    var drugs = await _drugRepository.GetAll()
                        .Where(d => drugIds.Contains(d.Id) && !d.IsDeleted)
                        .ToDictionaryAsync(d => d.Id, d => d, cancellationToken);

                    // 查询检查项目信息
                    var checkupItems = await _checkupItemRepository.GetAll()
                        .Where(c => checkupIds.Contains(c.Id) && !c.IsDeleted)
                        .ToDictionaryAsync(c => c.Id, c => c, cancellationToken);

                    // 查询检验项目信息
                    var testItems = await _testItemRepository.GetAll()
                        .Where(t => testIds.Contains(t.Id) && !t.IsDeleted)
                        .ToDictionaryAsync(t => t.Id, t => t, cancellationToken);

                    // 按开单申请ID分组明细
                    var detailGroups = details.GroupBy(d => d.ApplicationId).ToDictionary(g => g.Key, g => g.ToList());

                    // 填充明细信息
                    foreach (var dto in applicationDtos)
                    {
                        if (detailGroups.TryGetValue(dto.Id, out var detailList))
                        {
                            dto.Details = detailList.Select(d =>
                            {
                                var detailDto = _mapper.Map<PrescriptionDetailDto>(d);
                                
                                // 设置项目类型名称
                                detailDto.ItemTypeName = GetItemTypeName(d.ItemType);
                                
                                // 设置项目名称
                                detailDto.ItemName = GetItemName(d.ItemType, d.ItemId, drugs, checkupItems, testItems);
                                
                                return detailDto;
                            }).ToList();
                        }
                        else
                        {
                            dto.Details = new List<PrescriptionDetailDto>();
                        }
                    }
                }

                return new ApiResult<List<PrescriptionApplicationDto>>
                {
                    Code = ApiEnum.Success,
                    Msg = "获取开单申请列表成功",
                    Data = applicationDtos
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取开单申请列表时发生异常");
                return new ApiResult<List<PrescriptionApplicationDto>>
                {
                    Code = ApiEnum.Error,
                    Msg = "获取开单申请列表失败：" + ex.Message
                };
            }
        }

        /// <summary>
        /// 获取状态名称
        /// </summary>
        private string GetStatusName(int status)
        {
            return status switch
            {
                0 => "待审核",
                1 => "审核通过",
                2 => "审核驳回",
                3 => "已支付",
                4 => "已取消",
                _ => "未知状态"
            };
        }

        /// <summary>
        /// 获取项目类型名称
        /// </summary>
        private string GetItemTypeName(int itemType)
        {
            return itemType switch
            {
                1 => "药品",
                2 => "检查",
                3 => "检验",
                _ => "未知类型"
            };
        }

        /// <summary>
        /// 获取项目名称
        /// </summary>
        private string GetItemName(
            int itemType, 
            int itemId, 
            Dictionary<int, DrugInfoModel> drugs, 
            Dictionary<int, CheckupItemModel> checkupItems, 
            Dictionary<int, TestItemModel> testItems)
        {
            return itemType switch
            {
                1 => drugs.TryGetValue(itemId, out var drug) ? drug.DrugName : "未知药品",
                2 => checkupItems.TryGetValue(itemId, out var checkup) ? checkup.ItemName : "未知检查项目",
                3 => testItems.TryGetValue(itemId, out var test) ? test.ItemName : "未知检验项目",
                _ => "未知项目"
            };
        }
    }
} 